﻿// Mirco Töpfer

using System;
using System.IO;
using System.Threading;
using pheidippides.logging.Interfaces;
using System.Collections.Generic;

namespace pheidippides.logging.Classes
{
    public class TextFileLogger : ILogger
    {
        #region Private Members

        private readonly Thread workerThread;
        private readonly String LogFilePath;
        private LogLevel LoggerLogLevel;

        #endregion

        #region Constructor

        public TextFileLogger(String LogFilePath, LogLevel LoggerLogLevel)
        {
            this.LogFilePath = LogFilePath;
            this.LoggerLogLevel = LoggerLogLevel;

            workerThread = new Thread(Work);
            workerThread.IsBackground = true;
            workerThread.Priority = ThreadPriority.Lowest;
            workerThread.Start();

            LogDataManager.GetInstance().EnQueueLogEntry(new LogEntry("Logging wurde gestartet", LogLevel.Info));
        }

        #endregion

        #region Public Methods

        public void ChangeLogLevel(LogLevel LogLevel)
        {
            LoggerLogLevel = LogLevel;
        }

        public void LogMessage(string Message, LogLevel LogLevel)
        {
            LogEntry NewEntry = new LogEntry(Message, LogLevel);

            LogDataManager.GetInstance().EnQueueLogEntry(NewEntry);

            if (OnNewLogEntry != null)
                OnNewLogEntry(NewEntry);
        }

        public void LogException(String Message, Exception Ex, LogLevel LogLevel)
        {
            LogMessage(Message + Environment.NewLine + Ex.Message + Environment.NewLine + Ex, LogLevel);
        }

        public List<LogEntry> GetLogEntrys()
        {
            return LogDataManager.GetInstance().GetLast100LogEntrys();
        }

        public string GetLastLogEntrysString()
        {
            String Result = "";
            foreach (LogEntry item in GetLogEntrys())
            {
                Result = Result + item.TimeStamp.ToLongTimeString() + "." + item.TimeStamp.Millisecond.ToString("000") +
                         "\t" + item.LogLevel + "\t" + item.Message + Environment.NewLine;
            }
            return Result;
        }

        #endregion

        #region Public Events

        public event NewLogEntry OnNewLogEntry;

        #endregion

        #region Background Worker

        private void Work()
        {
            while (true)
            {
                while (LogDataManager.GetInstance().GetEntrysCount() > 0)
                {
                    LogEntry CurrentEntry = LogDataManager.GetInstance().DeQueueLogEntry();
                    LogDataManager.GetInstance().WriteLoggingPuffer(CurrentEntry);

                    if (CurrentEntry.LogLevel <= LoggerLogLevel)
                        WriteLogEntry(CurrentEntry);
                }
                Thread.Sleep(100);
            }
        }

        private void WriteLogEntry(LogEntry CurrentEntry)
        {
            FileStream Stream = null;
            StreamWriter Writer = null;
            try
            {
                Stream = new FileStream(LogFilePath, FileMode.Append);
                Writer = new StreamWriter(Stream);
                String LogEntryString = CurrentEntry.TimeStamp.ToShortDateString() + " " +
                                        CurrentEntry.TimeStamp.ToLongTimeString() + "." +
                                        CurrentEntry.TimeStamp.Millisecond.ToString("000") + "\t" +
                                        CurrentEntry.LogLevel + "\t" + CurrentEntry.Message;
                Writer.WriteLine(LogEntryString);
            }
            finally
            {
                if (Writer != null)
                    Writer.Close();

                if (Stream != null)
                    Stream.Close();
            }
        }

        #endregion
    }
}